const { DataSystemRoleModel } = require("../models/sys_role");
const { DataSystemRoleDeptModel } = require("../models/sys_role_dept");
const { fail, success, CODE } = require("../utils/utils");
const { DataSystemUserRoleModel } = require("../models/sys_user_role");
const { DataSystemDictDataModel } = require("../models/sys_dict_data");
const xlsx = require("node-xlsx");
const { DataSystemRoleMenuModel } = require("../models/sys_role_menu");
const { DataSystemDeptModel } = require("../models/sys_dept");

class SystemRoleController {
  /**
   * @description 添加权限
   * @param {String} role_name
   * @param {String} role_key
   * @param {Number} role_sort
   * @param {String} data_scope
   * @param {Number} menu_check_strictly
   * @param {Number} dept_check_strictly
   * @param {Number} status
   * @param {String} remark
   * @param {String} op_user_id
   */
  static async sysRoleAdd (ctx, next) {
    const {
      role_name,
      role_key,
      role_sort = 0,
      status = "1",
      data_scope = "5",
      menu_check_strictly = 1,
      dept_check_strictly = 1,
      remark,
      menu_ids = [],
    } = ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!role_name) {
        return (ctx.body = fail([], `请输入权限`));
      }
      const sysRoleInfo = await DataSystemRoleModel.findBySystemRoleName({
        role_name,
      });
      if (sysRoleInfo) {
        return (ctx.body = fail([], `权限已存在`));
      }
      const sysRoleCodeInfo = await DataSystemRoleModel.findBySystemRoleCode({
        role_key,
      });
      if (sysRoleCodeInfo) {
        return (ctx.body = fail([], `权限编码已存在`));
      }
      await DataSystemRoleModel.create({
        role_name,
        role_key,
        role_sort,
        data_scope,
        menu_check_strictly,
        dept_check_strictly,
        status,
        remark,
        op_user_id,
        menu_ids,
      });
      return (ctx.body = success([], `新增权限成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 更新权限
   * @param {Number} role_id
   * @param {String} role_name
   * @param {String} role_key
   * @param {Number} role_sort
   * @param {String} data_scope
   * @param {Number} menu_check_strictly
   * @param {Number} dept_check_strictly
   * @param {Number} status
   * @param {String} remark
   * @param {String} op_user_id
   * @param {String} menu_ids
   */
  static async sysRoleUpd (ctx, next) {
    const {
      role_id,
      role_name,
      role_key,
      role_sort,
      data_scope,
      menu_check_strictly,
      dept_check_strictly,
      menu_ids,
      status,
      remark,
    } = ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!role_id) {
        return (ctx.body = fail([], `请输入必填项`));
      }
      const sysRoleInfo = await DataSystemRoleModel.findBySystemRoleNameNeId({
        role_name,
        role_id,
      });
      if (sysRoleInfo) {
        return (ctx.body = fail([], `权限已存在`));
      }
      const sysRoleCodeInfo = await DataSystemRoleModel.findBySystemRoleKeyNeId(
        {
          role_key,
          role_id,
        }
      );
      if (sysRoleCodeInfo) {
        return (ctx.body = fail([], `权限编码已存在`));
      }
      await DataSystemRoleModel.update({
        role_name,
        role_key,
        role_sort,
        data_scope,
        menu_check_strictly,
        dept_check_strictly,
        status,
        remark,
        op_user_id,
        role_id,
      });
      await DataSystemRoleMenuModel.delete({ role_id });
      let bulk_menus = menu_ids.map((item) => {
        return {
          menu_id: item,
          role_id,
        };
      });
      await DataSystemRoleMenuModel.create({ data: bulk_menus });
      return (ctx.body = success([], `权限更新成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }

  /**
   * @description 分配数据权限
   * @param {Number} role_id
   * @param {String} data_scope
   * @param {String} op_user_id
   * @param {String} deptIds
   */
  static async sysRoleDataScope (ctx, next) {
    const { role_id, data_scope, dept_ids, dept_check_strictly } =
      ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!role_id || !data_scope) {
        return (ctx.body = fail([], `请输入必填项`));
      }
      const result = await DataSystemRoleModel.updateDateScope({
        data_scope,
        op_user_id,
        role_id,
        dept_check_strictly,
      });
      await DataSystemRoleDeptModel.delete(role_id);
      if (Array.isArray(dept_ids) && dept_ids.length) {
        let data = dept_ids.map((item) => {
          return {
            dept_id: item,
            role_id,
          };
        });
        await DataSystemRoleDeptModel.create({ data });
      }
      return (ctx.body = success([], `权限更新成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 删除权限
   * @param {Number} role_id
   */
  static async sysRoleDel (ctx, next) {
    const { role_id } = ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!role_id) {
        return (ctx.body = fail([], `role_id 获取失败`));
      }
      const result = await DataSystemRoleModel.delete({ op_user_id, role_id });
      return (ctx.body = success([], `权限删除成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }

  /**
   * @description 批量删除权限
   * @param {Number} ids
   */
  static async sysRoleDelByIds (ctx, next) {
    const { ids } = ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!ids || !Array.isArray(ids) || ids.length === 0) {
        return (ctx.body = fail([], `删除失败`));
      }
      const result = await DataSystemRoleModel.deleteByIds({ op_user_id, ids });
      return (ctx.body = success([], `权限批量删除成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }

  /**
   * @description 权限分页列表
   * @param {String} role_name
   * @param {String} role_key
   * @param {String} status
   * @param {String} limit
   * @param {String} size
   */
  static async sysRoleList (ctx, next) {
    try {
      const { page_num, page_size, role_name, role_key, status } =
        ctx.request.query;
      let limit = Number(page_num) || 1;
      let size = Number(page_size) || 10;
      const { result, count } = await DataSystemRoleModel.list({
        limit,
        size,
        role_name,
        role_key,
        status,
      });
      return (ctx.body = success(
        { result, total: count[0].count },
        `获取权限数据成功`
      ));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 权限所有列表
   * @param {String} name
   * @param {String} status
   */
  static async sysAllRoleList (ctx, next) {
    try {
      const { result } = await DataSystemRoleModel.all();
      return (ctx.body = success({ result }, `获取权限数据成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 获取授权用户 查询条件用户名称/手机号码
   * @param {String} name
   * @param {String} status
   */
  static async allocatedList (ctx, next) {
    try {
      const { role_id, page_num, page_size, phonenumber, user_name } = ctx.request.body;
      const { data_scope = "" } = ctx.state;
      let limit = Number(page_num) || 1;
      let size = Number(page_size) || 10;
      const { result, count } =
        await DataSystemUserRoleModel.findUserInfoByRoleId({
          role_id,
          data_scope,
          limit,
          size,
          phonenumber, user_name,
        });
      return (ctx.body = success({ result, total: count[0].count }, `查询成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 获取未授权用户 datascope 获取 查询条件用户名称/手机号码
   * @param {String} name
   * @param {String} status
   */
  static async unallocatedList (ctx, next) {
    try {
      const { role_id, page_num, page_size, phonenumber, user_name } = ctx.request.body;
      let limit = Number(page_num) || 1;
      let size = Number(page_size) || 10;
      const { data_scope = "" } = ctx.state;
      const { result, count } = await DataSystemUserRoleModel.findUserInfoNotInRoleId({
        role_id,
        data_scope,
        limit,
        size, phonenumber, user_name
      });
      return (ctx.body = success({ result, total: count[0].count }, `查询成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }

  /**
   * @description 批量添加用户
   * @param {String} name
   * @param {String} status
   */
  static async batchAddUser (ctx, next) {
    try {
      const { role_id, user_ids = [] } = ctx.request.body;
      if (!role_id || !user_ids.length) {
        return (ctx.body = fail([], `请输入必填项`));
      }
      const data = user_ids.map((user_id) => {
        return {
          role_id,
          user_id,
        };
      });
      await DataSystemUserRoleModel.bulkCreate({ data });
      return (ctx.body = success({}, `批量授权成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 取消用户授权
   * @param {String} name
   * @param {String} status
   */
  static async cancelAuthUser (ctx, next) {
    try {
      const { role_id, user_id } = ctx.request.body;
      if (!role_id || !user_id) {
        return (ctx.body = fail([], `请输入必填项`));
      }
      await DataSystemUserRoleModel.deleteByRoleIdAndUserId({
        role_id,
        user_id,
      });
      return (ctx.body = success({}, `撤销用户授权成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 取消用户授权
   * @param {String} name
   * @param {String} status
   */
  static async batchCancelUser (ctx, next) {
    try {
      const { role_id, user_ids = [] } = ctx.request.body;
      if (!role_id || !user_ids.length) {
        return (ctx.body = fail([], `请输入必填项`));
      }
      await DataSystemUserRoleModel.batchDestory({ role_id, user_ids });
      return (ctx.body = success({}, `批量撤销授权成功`));
    } catch (error) {
      return (ctx.body = fail([], error.message));
    }
  }
  /**
   * @description 通过角色id获取数据
   * @param {Number} role_id
   */
  static async sysRoleById (ctx, next) {
    const { role_id } = ctx.request.body;
    try {
      if (!role_id) {
        return (ctx.body = fail([], `role_id 获取失败`, CODE.BUSINESS_ERROR));
      }
      const result = await DataSystemRoleModel.findBySystemRoleId({
        role_id: Number(role_id),
      });
      return (ctx.body = success(result, `获取角色数据成功`, CODE.SUCCESS));
    } catch (error) {
      return (ctx.body = fail([], error.message, CODE.BUSINESS_ERROR));
    }
  }
  /**
   * @description 通过角色id获取数据
   * @param {Number} role_id
   */
  static async changeStatus (ctx, next) {
    const { role_id, status } = ctx.request.body;
    try {
      const { user_id: op_user_id } = ctx.state.user;
      if (!role_id) {
        return (ctx.body = fail([], `role_id 获取失败`, CODE.BUSINESS_ERROR));
      }
      await DataSystemRoleModel.updateStatus({
        op_user_id,
        role_id,
        status,
      });
      return (ctx.body = success([], `更新成功`, CODE.SUCCESS));
    } catch (error) {
      return (ctx.body = fail([], error.message, CODE.BUSINESS_ERROR));
    }
  }
  /**
   * @description 导出数据
   */
  static async sysRoleExport (ctx, next) {
    try {
      const { data_scope = "" } = ctx.state;
      const { role_name, role_key, status } = ctx.request.body;
      const { result } = await DataSystemRoleModel.findList({
        role_name,
        role_key,
        status,
        data_scope,
      });
      const sys_normal_disable_result =
        await DataSystemDictDataModel.findBySystemdDictType({
          dict_type: "sys_normal_disable",
        });
      let data = result.map((item) => {
        let current_staus = sys_normal_disable_result.find(
          (snd) => snd.dict_value === item.status
        );
        item.status = current_staus ? current_staus.dict_label : item.status;
        return item;
      });
      const excelData = [
        ["角色名称", "权限字符", "显示顺序", "状态", "备注", "创建时间"],
        ...data.map((item) => [
          item.role_name,
          item.role_key,
          item.role_sort,
          item.status,
          item.remark,
          item.create_time,
        ]),
      ];
      const buffer = xlsx.build([{ name: "Sheet1", data: excelData }]);
      // 设置返回的http header信息，告诉浏览器该文件是一个excel文件
      ctx.set(
        "Content-Type",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      );
      ctx.set(
        "Content-Disposition",
        "attachment; filename=" + encodeURIComponent("角色数据.xlsx")
      );

      // 将生成的excel文件发送给客户端
      ctx.body = buffer;
    } catch (error) {
      return (ctx.body = fail([], error.message, CODE.BUSINESS_ERROR));
    }
  }
}

module.exports = {
  SystemRoleController,
};
